using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEditor;
using UnityEngine;

namespace EntityKit.Editor
{
    public class CodeExportWindow : EditorWindow
    {
        public static void ShowCodeExportWindow()
        {
            CodeExportWindow window = GetWindow<CodeExportWindow>();
            window.titleContent = new GUIContent("代码导出工具");
            window.minSize = new Vector2(600, 500);
            window.Show();
        }
        
        private bool m_AddLineNumbers = false;
        private bool m_RemoveEmptyLines = false;
        private Vector2 m_ScrollPosition;
        private List<string> m_FolderPaths = new List<string>();
        private string m_LastSelectedPath = "";

        private void OnGUI()
        {
            GUI.backgroundColor = new Color(0.25f, 0.25f, 0.25f);
            
            EditorGUILayout.BeginVertical(GUILayout.ExpandHeight(true));
            {
                DrawHeader();
                DrawDirectorySection();
                DrawSettingsSection();
                DrawExportSection();
            }
            EditorGUILayout.EndVertical();
            GUI.backgroundColor = Color.white;
        }

        private void DrawHeader()
        {
            EditorGUILayout.BeginVertical(EditorStyles.helpBox);
            {
                GUIStyle titleStyle = new GUIStyle(EditorStyles.largeLabel)
                {
                    fontSize = 16,
                    fontStyle = FontStyle.Bold,
                    alignment = TextAnchor.MiddleCenter,
                    normal = { textColor = Color.white }
                };
                
                EditorGUILayout.LabelField("代码导出工具", titleStyle);
                EditorGUILayout.HelpBox("选择需要导出代码的目录，工具将递归导出该目录下所有.cs文件的内容到一个文本文件中。", MessageType.Info);
            }
            EditorGUILayout.EndVertical();
        }

        private void DrawDirectorySection()
        {
            EditorGUILayout.BeginVertical(EditorStyles.helpBox);
            {
                EditorGUILayout.BeginHorizontal();
                {
                    EditorGUILayout.LabelField("导出目录设置", EditorStyles.boldLabel);
                    GUILayout.FlexibleSpace();
                    EditorGUILayout.LabelField($"已配置目录: {m_FolderPaths.Count}", EditorStyles.miniLabel);
                }
                EditorGUILayout.EndHorizontal();

                EditorGUILayout.Space(5);
                
                EditorGUILayout.BeginHorizontal();
                {
                    GUILayout.FlexibleSpace();
                    if (GUILayout.Button("+ 添加目录", GUILayout.Width(100)))
                    {
                        m_FolderPaths.Add("");
                    }
                    GUILayout.FlexibleSpace();
                }
                EditorGUILayout.EndHorizontal();

                EditorGUILayout.Space(5);
                
                m_ScrollPosition = EditorGUILayout.BeginScrollView(m_ScrollPosition, GUILayout.Height(Mathf.Min(200, m_FolderPaths.Count * 25 + 10)));
                {
                    List<int> itemsToRemove = new List<int>();
                    
                    for (int i = 0; i < m_FolderPaths.Count; i++)
                    {
                        DrawDirectoryItem(i, itemsToRemove);
                    }

                    for (int i = itemsToRemove.Count - 1; i >= 0; i--)
                    {
                        int index = itemsToRemove[i];
                        if (index >= 0 && index < m_FolderPaths.Count)
                        {
                            m_FolderPaths.RemoveAt(index);
                        }
                    }
                }
                EditorGUILayout.EndScrollView();
            }
            EditorGUILayout.EndVertical();
        }

        private void DrawDirectoryItem(int index, List<int> itemsToRemove)
        {
            EditorGUILayout.BeginHorizontal();
            {
                EditorGUILayout.LabelField($"目录 {index + 1}:", GUILayout.Width(50));
                
                string currentPath = m_FolderPaths[index];
                string displayPath = string.IsNullOrEmpty(currentPath) ? "未选择目录" : currentPath;
                
                EditorGUI.BeginDisabledGroup(true);
                EditorGUILayout.TextField(displayPath, GUILayout.ExpandWidth(true), GUILayout.Height(20));
                EditorGUI.EndDisabledGroup();
                
                if (GUILayout.Button("选择目录", GUILayout.Width(70), GUILayout.Height(20)))
                {
                    string selectedPath = EditorUtility.OpenFolderPanel("选择代码目录", !string.IsNullOrEmpty(m_LastSelectedPath) ? m_LastSelectedPath : Application.dataPath, "");
                    
                    if (!string.IsNullOrEmpty(selectedPath))
                    {
                        m_FolderPaths[index] = selectedPath;
                        m_LastSelectedPath = selectedPath;
                    }
                }
                
                if (GUILayout.Button("删除", GUILayout.Width(50), GUILayout.Height(20)))
                {
                    itemsToRemove.Add(index);
                }
            }
            EditorGUILayout.EndHorizontal();
            
            EditorGUILayout.Space(2);
        }

        private void DrawSettingsSection()
        {
            EditorGUILayout.BeginVertical(EditorStyles.helpBox);
            {
                EditorGUILayout.LabelField("导出设置", EditorStyles.boldLabel);
                
                EditorGUILayout.Space(5);
                
                EditorGUILayout.BeginHorizontal();
                {
                    m_AddLineNumbers = EditorGUILayout.Toggle(m_AddLineNumbers, GUILayout.Width(20));
                    EditorGUILayout.LabelField("添加行号", GUILayout.Width(60));
                    EditorGUILayout.LabelField("为所有导出文件累计添加行号", EditorStyles.miniLabel);
                }
                EditorGUILayout.EndHorizontal();
                
                EditorGUILayout.Space(2);
                
                EditorGUILayout.BeginHorizontal();
                {
                    m_RemoveEmptyLines = EditorGUILayout.Toggle(m_RemoveEmptyLines, GUILayout.Width(20));
                    EditorGUILayout.LabelField("去除空行", GUILayout.Width(60));
                    EditorGUILayout.LabelField("删除导出文件中的空行", EditorStyles.miniLabel);
                }
                EditorGUILayout.EndHorizontal();
            }
            EditorGUILayout.EndVertical();
        }

        private void DrawExportSection()
        {
            if (m_FolderPaths.Count == 0) return;
            
            EditorGUILayout.BeginVertical(EditorStyles.helpBox);
            {
                EditorGUILayout.LabelField("导出操作", EditorStyles.boldLabel);
                
                EditorGUILayout.Space(5);
                
                EditorGUILayout.BeginHorizontal();
                {
                    GUILayout.FlexibleSpace();
                    
                    if (GUILayout.Button("导出代码", GUILayout.Width(200), GUILayout.Height(30)))
                    {
                        ExportCode();
                    }
                    
                    GUILayout.FlexibleSpace();
                }
                EditorGUILayout.EndHorizontal();
            }
            EditorGUILayout.EndVertical();
        }

        private void ExportCode()
        {
            string defaultFileName = $"outC#{PlayerSettings.productName}.txt";
            string saveFile = EditorUtility.SaveFilePanel("保存代码文件", "", defaultFileName, "txt");
            
            if (!string.IsNullOrEmpty(saveFile))
            {
                try
                {
                    DoOutputCode(saveFile);
                    EditorUtility.RevealInFinder(saveFile);
                    ShowNotification(new GUIContent("代码导出完成!"));
                }
                catch (Exception ex)
                {
                    Debug.LogError($"导出代码时出错: {ex.Message}");
                    EditorUtility.DisplayDialog("错误", $"导出代码时出错:\n{ex.Message}", "确定");
                }
            }
        }

        private void DoOutputCode(string txtPath)
        {
            using (FileStream stream = new FileStream(txtPath, FileMode.Create, FileAccess.Write))
            using (StreamWriter writer = new StreamWriter(stream, Encoding.UTF8))
            {
                // 写入文件头信息
                // writer.WriteLine($"# 代码导出文件");
                // writer.WriteLine($"# 导出时间: {DateTime.Now:yyyy-MM-dd HH:mm:ss}");
                // writer.WriteLine($"# 项目名称: {PlayerSettings.productName}");
                // writer.WriteLine($"# 添加行号: {m_AddLineNumbers}");
                // writer.WriteLine($"# 去除空行: {m_RemoveEmptyLines}");
                // writer.WriteLine();
                
                int totalFiles = 0;
                int totalLines = 0;
                int globalLineNumber = 1; 
                
                foreach (string path in m_FolderPaths)
                {
                    if (!string.IsNullOrEmpty(path) && Directory.Exists(path))
                    {
                        // writer.WriteLine($"# ===== 目录: {path} =====");
                        // writer.WriteLine();
                        
                        string codeContent = GetAllCodeFromPath(path, out int fileCount, out int lineCount, ref globalLineNumber);
                        writer.Write(codeContent);
                        //writer.WriteLine();
                        
                        totalFiles += fileCount;
                        totalLines += lineCount;
                    }
                }
                
                // 写入统计信息
                // writer.WriteLine($"# 导出完成");
                // writer.WriteLine($"# 总文件数: {totalFiles}");
                // writer.WriteLine($"# 总代码行数: {totalLines}");
                // writer.WriteLine($"# 总目录数: {m_FolderPaths.Count}");
                Debug.Log("代码导出完成");
                Debug.Log($"总文件数: {totalFiles}");
                Debug.Log($"总代码行数: {totalLines}");
                Debug.Log($"总目录数: {m_FolderPaths.Count}");
                
            }
        }

        private string GetAllCodeFromPath(string path, out int fileCount, out int lineCount, ref int globalLineNumber)
        {
            fileCount = 0;
            lineCount = 0;
            
            if (string.IsNullOrEmpty(path) || !Directory.Exists(path))
            {
                return "# 错误: 指定的路径不存在";
            }
            
            StringBuilder builder = new StringBuilder();
            string[] files = Directory.GetFiles(path, "*.cs", SearchOption.AllDirectories);
            fileCount = files.Length;

            for (int i = 0; i < files.Length; i++)
            {
                try
                {
                    string relativePath = files[i].Replace(path, "").TrimStart(Path.DirectorySeparatorChar);
                    //builder.AppendLine($"// ===== 文件: {relativePath} =====");
                    
                    string fileContent = File.ReadAllText(files[i]);
                    string processedContent = ProcessFileContent(fileContent, out int fileLineCount, ref globalLineNumber);
                    builder.AppendLine(processedContent);
                    //builder.AppendLine();
                    
                    lineCount += fileLineCount;
                    
                    if (EditorUtility.DisplayCancelableProgressBar("导出代码", $"正在导出: {relativePath}", (float)i / files.Length))
                    {
                        break;
                    }
                }
                catch (Exception ex)
                {
                    Debug.LogError($"读取文件 {files[i]} 时出错: {ex.Message}");
                }
            }
            
            EditorUtility.ClearProgressBar();
            return builder.ToString();
        }

        private string ProcessFileContent(string content, out int lineCount, ref int globalLineNumber)
        {
            string[] lines = content.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None);
            List<string> processedLines = new List<string>();
            lineCount = 0;

            for (int i = 0; i < lines.Length; i++)
            {
                string line = lines[i];
                bool isEmptyLine = string.IsNullOrWhiteSpace(line);
                
                // 如果启用了去除空行且当前是空行，则跳过
                if (m_RemoveEmptyLines && isEmptyLine)
                {
                    continue;
                }
                
                // 如果启用了添加行号，为每行添加行号（使用全局行号）
                if (m_AddLineNumbers)
                {
                    //0001: ,0002:
                    //line = $"{globalLineNumber:D4}: {line}";
                    line = $"{globalLineNumber}: {line}";
                    globalLineNumber++;
                }
                
                processedLines.Add(line);
                lineCount++;
            }
            
            return string.Join(Environment.NewLine, processedLines);
        }

        private void OnEnable()
        {
            m_FolderPaths ??= new List<string>();
            
            if (m_FolderPaths.Count == 0)
            {
                m_FolderPaths.Add(Application.dataPath);
            }
        }
    }
}